____ _ _ _ _
| _ \ ___ | |_ (_) _ __ ___ __| | (_) __ _
| |_) | / _ \ | __| | | | '_ \ / _ \ / _| | | | / _ |
| _ < | __/ | |_ | | | |_) | | __/ | (_| | | | | (_| |
|_| \_\ \___| \__| |_| | .__/ \___| \__,_| |_| \__,_|
|_|
- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b- `b
Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―Β―
Generische Programmierung in Java
part 5/6 Β· 18.5 KB total
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Integer i = list.get(index); // Typfehler: Es muss sich bei '? extends Number'
// nicht um ein Integer handeln.
Integer j = (Integer) list.get(index); // OK
Die Zuweisung
? extends T
β
T (oder Basisklasse)
ist also erlaubt, nicht aber die Zuweisung
? extends T
β
abgeleitet von T
Generics bieten also wie Arrays kovariantes Verhalten, verbieten aber alle Operationen, die typunsicher sind.
Kontravarianz
Kontravarianz bezeichnet das Verhalten der Vererbungshierarchie des generischen Typs entgegen der Hierarchie seines Typparameters. Γbertragen auf das obige Beispiel wΓΌrde das bedeuten: Eine Liste<Number> wΓ€re zuweisungskompatibel zu einer Liste<Double>. Dies wird folgendermaΓen bewerkstelligt:
List<? super Double> list;
list = new ArrayList<Number>();
list = new ArrayList<Double>();
list = new ArrayList<Object>();
Ein Objekt, das sich kontravariant verhΓ€lt, darf keine Annahmen darΓΌber machen, inwiefern ein Element vom Typ V von T abgeleitet ist, wobei T der lower Typebound ist (im Beispiel von ? super Double ist T Double). Deshalb kann aus den obigen Listen nicht gelesen werden:
// Fehler: 'list' kΓΆnnte vom Typ List<Object> sein
Number x = list.get(index);
// Fehler: 'list' kΓΆnnte List<Object> oder List<Number> sein
Double x = list.get(index);
// Die einzige Ausnahme: Objects sind auf jeden Fall in der Liste
Object x = list.get(index);
Nicht erlaubt, da nicht typsicher, ist also die Zuweisung ? super T β (abgeleitet von Object)
Unschwer zu erraten: Im Gegenzug kann in eine solche Liste ein Element abgelegt werden:
List<? super Number> list;
list.add(new Double(3.0)); // OK: 'list' hat immer den Typ List<Number>
// oder List<Basisklasse von Number>. Damit
// ist die Zuweisung Double -> T immer erlaubt.
UneingeschrΓ€nkte parametrische Polymorphie
Zu guter Letzt bieten Generics noch gΓ€nzlich polymorphes Verhalten an. Hierbei kann keinerlei Aussage ΓΌber die Typparameter gemacht werden, denn es wird in beide Richtungen keine Grenze angegeben. DafΓΌr wurde die Wildcard definiert. Sie wird durch ein Fragezeichen reprΓ€sentiert.
List<?> list;
list = new ArrayList<Integer>();
list = new ArrayList<Object>();
list = new ArrayList<String>();
// ...
Der Typparameter selbst kann hierbei nicht genutzt werden, da keine Aussage mΓΆglich ist. Lediglich die Zuweisung T β Object ist erlaubt, da T auf jeden Fall ein Object ist. Im Gegenzug ist garantiert, dass der Code mit allen Ts arbeiten kann.
NΓΌtzlich kann so etwas sein, wenn man nur mit dem generischen Typ arbeitet:
// Keine Informationen ΓΌber den Typparameter nΓΆtig, kann ''beliebige'' Listen
// aufnehmen.
int readSize(List<?> list) {
return list.size();
}
Zur Verdeutlichung, dass hier Wildcards unnΓΆtig sind, und es eigentlich gar nicht um irgendeine Varianz geht, sei folgende Implementierung der obigen Funktion angegeben:
<T> int readSize(List<T> list) {
return list.size();
}
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ